home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-10-24 | 7.9 KB | 227 lines | [TEXT/MPS ] |
- ; Macintosh Toolbox and OS-trap bypass routines.
- ; Copyright © 1987 Michael S. Morton
- ;
- ; History: 10-May-87 - MM - Initial version.
- ; 22-Oct-87 - MM - Neatened for publication.
-
- BLANKS ON
- STRING ASIS
- PRINT OFF
- LOAD 'tlAsmSyms.sym'
- PRINT ON
-
- ; Impure code! Should be in a segment which is locked in memory.
- SEG 'LOCKDSEG' ; *** change to a locked segment ***
-
- ;--------------------------------------------------------------------------
- ; Each Toolbox routine starts out life as:
- ; 2 <pure copy of trap word>
- ; entry: 2 <trap word with auto-pop bit>
- ; 4 <four bytes unused>
- ;
- ; The evaluator changes this to:
- ; 2 <pure copy of trap word>
- ; entry: 6 JMP <actual address>
- ;
- ; Either form is callable with a JSR because the former includes the “auto-pop”
- ; bit, so the Toolbox routine returns to its caller’s caller. Offsets are:
-
- tTrap: EQU 0 ; pure copy of trap
- tJump: EQU 2 ; JMP xxx.L instruction
- tAddress: EQU 4 ; address to jump to
- tLength: EQU 8 ; length of one block
-
- ; The “qtTool” macro generates code for one “qt” Toolbox routine.
- ;
- ; args: routine - Name for routine. Typically “qt” plus trap name.
- ; trap - Name of the trap, eg, “_MoveTo”.
-
- MACRO
- qtTool
- EXPORT &Syslst[1] ; define the “qtXXX” routine globally
- &Syslst[2] ; first, a pure copy of the trap word
- &Syslst[1] &Syslst[2] autoPop ; entry: if not overwritten, just trap
- ds.b 4 ; reserve room for overwriting
- ENDM
-
- ;--------------------------------------------------------------------------
- ; Each OS trap bypass routine is 28 bytes long. The unevaluated routine is:
- ; 2 <pure copy of trap word>
- ; entry: 2 <trap word> ; only this part…
- ; 2 RTS ; …gets executed before eval
- ; 4 MOVE.W #<xxx>, D1 ; trap word patched here
- ; 4 MOVE.W #<xxx>, D2 ; trap number patched here
- ; 6 JSR xxx.L ; routine address patched here
- ; 4 MOVEM.L (SP)+, D1-D2/A1-A2 ; register list patched here
- ; 2 TST.W D0 ; set condition codes
- ; 2 RTS ; and return
- ; After the evaluator is done, the routine becomes:
- ; 2 <pure copy of trap word>
- ; entry: 4 MOVEM.L D1-D2/A1-A2, -(SP) ; (saves A0 too, if bit 8 set)
- ; 4 MOVE.W #<trapword>, D1 ; get trap word in D1
- ; 4 MOVE.W #<trapword & $01FF>, D2 ; …and trap number
- ; 6 JSR xxx.L ; call the routine
- ; 4 MOVEM.L (SP)+, D1-D2/A1-A2 ; (gets A0 too, if bit 8 set)
- ; 2 TST.W D0 ; set condition codes
- ; 2 RTS ; and return
-
- oTrap: EQU 0 ; original trap word
- oSave: EQU 2 ; for MOVEM.L xxx, -(SP) to go
- oTrapWord: EQU 8 ; for trap word in MOVE.W #xxx, D1
- oTrapNum: EQU 12 ; for trap number in MOVE.W #xxx, D2
- oAddress: EQU 16 ; address to jump to
- oRestore: EQU 22 ; for second copy of MOVEM regs list
- oLength: EQU 28 ; length of one block
-
- ; The “qtOS” macro generates code for one “qt” OS routine.
- ;
- ; args: routine - Name for trap routine. Typically “qt” plus trap name.
- ; trap - Name of the trap, eg, “_GetHandleSize”.
-
- MACRO
- qtOS
- EXPORT &Syslst[1] ; define the “qtXXX” routine globally
- &Syslst[2] ; pure copy of trap word
- &Syslst[1] &Syslst[2] ; entry: if not overwritten, just trap…
- RTS ; …and return
- MOVE.W #$5555, D1 ; get trap word in D1, for OS routine
- MOVE.W #$5555, D2 ; …and trap number
- JSR $55555555 ; leave space for a longword address
- MOVEM.L (SP)+, D1-D2/A1-A2 ; assume A0 not in the register list
- TST.W D0 ; set condition codes
- RTS ; and return
- ENDM
-
- ;--------------------------------------------------------------------------
- ; Resource type and ID for the flag used to disable the trickery.
-
- qtrpType: EQU 'QTRP' ; resource type for flag
- qtrpId: EQU 257 ; resource ID for flag
-
-
- ; qtEval
- ;
- ; description:
- ; Update the routines so they jump directly into the ROM, or wherever.
- ; This routine should be called at startup, and each time the application
- ; thinks anyone has (or might have) called SetTrapAddress.
- ;
- ; uses: (no registers)
-
- qtEval: PROC EXPORT
-
- ; Stuff used in patching together routines:
- jmpInst: EQU $4EF9 ; opcode word of JMP xxx.L
-
- OSregs: REG D1-D2/A1-A2 ; registers saved by OS dispatcher
- OSregs2:REG D1-D2/A0-A2 ; registers saved when bit 8 is zero
-
- MOVEM.L D0-D2/A0-A2, -(SP) ; save caller’s registers
-
- ; First, see if we’ve already been told not to do our thing:
- LEA qtEnabled, A2 ; point to the flag
- TST.B (A2) ; have we snuffed it already?
- BEQ evalEnd ; yes: nothing to do
-
- ; Second, decide if the resource flag allows us to map/cache.
- SUBQ #4, SP ; make room for function result
- MOVE.L #qtrpType, -(SP) ; pass the type…
- MOVE.W #qtrpId, -(SP) ; …and ID
- _GetResource ; try to find our flag
- MOVE.L (SP)+, A0 ; pop result…
- MOVE.L A0, D0 ; …and test for NIL
- BEQ.S evalTurnOff ; no such thing? go flag this and exit
-
- MOVE.L (A0), A1 ; deref. handle; point to rsrc with A0
- MOVE.W (A1), D2 ; pick up first word, to check later
- MOVE.L A0, -(SP) ; pass handle…
- _ReleaseResource ; …and get rid of it
-
- TST.W D2 ; now check -- did rsrc start with zero?
- BNE.S evalTurnOff ; …no: we don’t yet do selective disable
-
- ; Nothing forbids hackery. Evaluate all the toolbox bypass routines.
- LEA qtToolStart, A1 ; point to first routine
- LEA qtToolEnd, A2 ; point to just after last routine
- MOVE.W #jmpInst, D1 ; get a JMP xxx.L instruction
- BRA.S toolEnd ; check for no routines
-
- toolLp: MOVE.W tTrap(A1), D0 ; pick up the trap number in D0.w
- _GetTrapAddress newTool ; ask where this routine lives
- MOVE.L A0, tAddress(A1) ; store address first, THEN…
- MOVE.W D1, tJump(A1) ; …the JMP, so routine’s always OK
- ADDQ #tLength, A1 ; advance to the next routine
-
- toolEnd:CMP.L A2, A1 ; at (or past) end of toolbox routines?
- BLO.S toolLp ; nope: go evaluate another one
-
- ; Evaluate all the OS bypass routines.
- LEA qtOSStart, A1 ; point to first…
- LEA qtOSEnd, A2 ; …and to just after last
- BRA.S osEnd ; handle degenerate case
-
- osLoop: MOVE.W oTrap(A1), D0 ; pick up trap number
- MOVE.W D0, D2 ; copy it for later use (BTST, etc.)
- _GetTrapAddress newOS ; find where the routine lives
- MOVE.L A0, oAddress(A1) ; save routine address in JMP xxx.L
-
- MOVE.W D2, oTrapWord(A1) ; fill in MOVE.W #trapword, D1
- AND.W #$01FF, D2 ; get just the trap number
- MOVE.W D2, oTrapNum(A1) ; and store that in MOVE.W #trapnum, D2
-
- ; Decide whether the saved registers include A0.
- MOVE.L OSent, D0 ; assume we want usual registers saved…
- MOVE.L OSexit, D1 ; …and restored
- BTST #8, D2 ; but should we save A0, too?
- BNE.S osLp1 ; nope: OSent’s registers are fine
- MOVE.L OSent2, D0 ; yep: use reg list which includes A0
- MOVE.L OSexit2, D1 ; …and ditto for one which saves A0
- osLp1: MOVE.W D1, oRestore(A1) ; store register list for restore
- MOVE.L D0, oSave(A1) ; lastly, get rid of 1st trap
- ADD #oLength, A1 ; advance to the next routine
-
- osEnd: CMP.L A2, A1 ; at the end?
- BLO.S osLoop ; nope: go do another
-
- evalEnd:MOVEM.L (SP)+, D0-D2/A0-A2 ; restore caller’s registers
- RTS
-
- ; Here when the resource forbids caching. A2 points to the flag.
- evalTurnOff:
- SF (A2) ; …disable it for faster call next time
- BRA.S evalEnd ; clean up and exit
-
- ; *** Impure *** flag: 0 means mapping disabled; non-zero means enabled.
- qtEnabled:
- DC.B $FF,00 ; initially enabled; 2nd byte to align
-
- ; Instructions and register lists to stick into OS routines. Each is 2 words.
- OSent: MOVEM.L OSregs, -(SP)
- OSent2: MOVEM.L OSregs2, -(SP)
- OSexit: MOVEM.L (SP)+, OSregs
- OSexit2:MOVEM.L (SP)+, OSregs2
-
- ; Toolbox trap replacement routines. To be re-evaluated, these must be between
- ; qtToolStart and qtToolEnd. Nothing else must be in here -- the evaluator
- ; walks through this as an array.
- qtToolStart: ; Beginning of Toolbox trap replacement routines.
-
- qtTool qtMoveTo,_MoveTo
- qtTool qtSetPort,_SetPort
- ; …add your own here…
-
- qtToolEnd: ; End of Toolbox trap replacement routines.
-
- ; OS trap replacement routines. As with toolbox, keep only these in here.
- qtOSStart: ; Beginning of OS trap replacement routines.
-
- qtOS qtHLock,_HLock
- qtOS qtHUnlock,_HUnlock
- ; …add your own here…
-
- qtOSEnd: ; End of OS trap replacement routines.
-
- END
-
-
-